<!DOCTYPE html>
<html lang="zh-CN">

<head>
	<meta charset="UTF-8" />
	<title>正则表达式必知必会</title>
	<link rel="stylesheet" href="../style/css/article.css">
	<!-- <script src="js/a.js"></script> -->
</head>

<body>
<a id="top" href="#"></a>
<div id="particles-js"></div>
<div class="meta">
<h1>Meta</h1>
<ul>
<li>正则表达式入门级别的一本不错的书, 更像是一本用户入门学习手册而非一本字典级参考手册, 正如作者所说, 在学习和使用正则表达式的时候, 重要的并不是你知道多少个特殊字符, 而是你会不会运用它们去解决实际问题, 学以致用, 致用以学, 最近我的问题在于为了学习而学习, 而非为了应用而学习, 事倍功半, 人的精力有限, 时间有限, 又哪能做到样样深耕呢, 对于接触的大多领域都只需掌握一些核心概念和基本语法就好</li>
</ul>
<div class="h2i1">
<h2>引言</h2>
<ul>
<li>在学习和使用正则表达式的时候, 重要的并不是你知道多少个特殊字符, 而是你会不会运用它们去解决实际问题</li>
<ul>
<li>学以致用, 致用以学, 最近我的问题在于为了学习而学习, 而非为了应用而学习, 事倍功半</li>
<li>精力有限, 时间有限, 又哪能做到样样深耕呢, 对于接触的大多领域都只需掌握一些核心概念和基本语法就好.</li>
</ul>
<li>本书架构, 从简单的字符串匹配开始入手, 后序介绍一些复杂一些的专题, e.g. 回溯引用/后向引用(backreference), 条件性求值(conditional evaluation)和前后查找(looking-around)</li>
</ul>
</div><div class="h2i2">
<h2>C1 正则表达式入门</h2>
<ul>
<li>regular expression -> regex</li>
<li>用途, 进行文本匹配+[替换]</li>
<li>比较迷你, 一般嵌入到其他工具中, 应用程序大多用菜单访问regex, 程序设计语言大都通过函数or类来使用regex</li>
<li>计算机从来都是做中学学科, 不经过实践的学习在CS领域事倍功半</li>
</ul>
</div><div class="h2i3">
<h2>C2 匹配单个字符</h2>
<ul>
<li>. 除换行符以外的任意单个字符, 如果需要.的本身含义, 用转义字符\</li>
</ul>
</div><div class="h2i4">
<h2>C3 匹配一组字符</h2>
<ul>
<li>用[]定义一个字符集合, 里面可以写想要匹配的字符, e.g. [ab], </li>
<ul>
<li>在[]中使用-可以定义一个字符区间, e.g. [A-Za-z0-9] 在[]外使用-就是一个普通的字符, 所以在regex中使用-不需要被转义</li>
</ul>
<li>[^a-z0-9], 先定义一个字符区间, 而后对其取非, 而不是只对^后跟着的字符区间取非</li>
</ul>
</div><div class="h2i5">
<h2>C4 使用元字符</h2>
<ul>
<li>前面接触到的元字符, `. [ ] \`</li>
<li>空白元字符</li>
<ul>
<li>[\b] 回退(并删除)一个字符(Backspace键), 这个是用来匹配退格字符的, 不在\s中</li>
<li>\f 换页符</li>
<li>\n 换行符, \r 回车符, \t 制表符</li>
<li>\v 垂直制表符</li>
<li>\d is [0-9], \D is [^0-9]</li>
<li>\w is [a-zA-Z0-9_], \W is ^ of \w</li>
<li>\s is [\f\n\r\t\v], 任意一个空白字符, \S任意非空字符</li>
</ul>
<li>POSIX字符类, 一种字符集合中的简写形式, 并非所有的regex的实现都支持</li>
</ul>
</div><div class="h2i6">
<h2>C5 重复匹配</h2>
<ul>
<li>+, 一到多, [0-9]+, 代表1-多个连续数字</li>
<ul>
<li>注意区分[0-9+], 匹配一个字符, 可以是数字或+</li>
</ul>
<li>*, 零到多</li>
<li>?, 0 or 1</li>
<ul>
<li>解决Windows/Linux系统下回车问题就可以用 [\r]?\n</li>
<li>写\r?\n也是一样的, 第一种写法定义一个字符集合, 集合里只有\r这样的一种字符, 和第二种写法功能相同, 对读者更友好一点, 读起来不会有歧义.</li>
</ul>
<li>上述三种都是元字符, 匹配本身需要转义, 放到字符集合里也是本身, 加了转义也没什么问题</li>
<li>制定精确的重复次数{}</li>
<ul>
<li>{a} 重复a次</li>
<li>{a, b} 重复[a, b]次</li>
<li>{a, } 至少重复a次</li>
</ul>
<li>*, +, {a, }这三个都没有上限, 都是贪婪型的, 尽可能匹配的长</li>
<li>*?, +?, {a, }?是其对于的懒惰版本, 尽可能匹配的短</li>
</ul>
</div><div class="h2i7">
<h2>C6 位置匹配</h2>
<ul>
<li>the border of a word(w in Vim)</li>
<li>\< matches the pos of \W and \w, \> matches that of \w and \W</li>
<li>\b matches the pos of \w and \W or that of \W and \w</li>
<li>the border of a string(W in Vim)</li>
<li>^ matches the start of a string, $ matches end</li>
<li>(?m), regard \n as a start/end of string</li>
</ul>
</div><div class="h2i8">
<h2>C7 子表达式</h2>
<ul>
<li>用元字符()进行分组</li>
</ul>
</div><div class="h2i9">
<h2>C8 回溯引用backreference</h2>
<ul>
<li>解决HTML中Head标签匹配, 用`<[hH][1-6]>.*?</[hH][1-6]>`来找出所有的head标签, 现在存在的问题是<h2>a</h3>也会被匹配进来, 也就是结束标签对开始标签的情况一无所知, 回溯引用就是用来解决这类问题的</li>
<li>比如匹配两个连续的单词怎么实现, 需要先知道第一个单词是什么, 才能控制第二个和它一不一样, 实现 `[ ]+(\w+)[ ]+\1`</li>
<ul>
<li>[ ]+代表1-多个space, 用()把\w+括起来, 做成一个子表达式, 然后用\1引用pattern中的第一个子表达式, 想一下Java中对正则表达式的实现, 把子表达式的sIndex和eIndex+1存到groups[2]和groups[3]中, 后续即可引用</li>
</ul>
<li>这种按位置的捕获方式用\数字进行引用, 当想改逻辑的时候可能要改的地方有点多, 可以用`命名捕获`, 给子表达式起个名字, 这样改变相对位置也不用改后面引用位置的语句了, 命名捕获是否支持要看具体的实现</li>
</ul>
</div><div class="h2i10">
<h2>C9 前后查找lookaround</h2>
<ul>
<li>regex常见的实现都支持向前查找lookahead, 部分支持向后查找lookbehind, Java是支持的</li>
</ul>
</div><div class="h2i11">
<h2>C10 嵌入条件</h2>
<ul>
<li>当前面是不同的匹配时向后找不同的匹配, 类似于编程语言中的三元运算符</li>
</ul>
</div><div class="h2i12">
<h2>附录A</h2>
<div class="h3i1">
<h3>A.12 Perl</h3>
<ul>
<li>m/pattern/</li>
<li>s/pattern/pattern/</li>
		</ul>
</div></div>	</div>
<script src="../style/js/particles.min.js"></script>
<script src="../style/js/particles.config.js"></script>
</body>
</html>
